<template>
  <div
    class="artworkDrawer-container"
    :class="[visible && isHide ? 'show' : 'hide']"
  >
    <div class="artworkDrawer-body">
      <div class="header">
        图模联动<a-icon type="close" @click="handleClose()" />
      </div>
      <div class="body">
        <div class="search-condition">
          <a-input-search
            v-model.trim="keyWord"
            @search="filterTreeData()"
            style="width: 100%"
            placeholder="请输入关键字"
          />
        </div>
        <div class="tree-container">
          <a-spin :spinning="spinning">
            <a-empty v-if="treeData.length == 0" :description="false" />
            <a-tree
              v-else
              show-icon
              :expanded-keys="expandedKeys"
              :auto-expand-parent="autoExpandParent"
              :selected-keys="selectedKeys"
              :tree-data="treeData"
              @expand="onExpand"
              @select="onSelect"
              :replaceFields="{
                children: 'children',
                title: 'nodeName',
                key: 'id',
              }"
            >
              <!-- 自定义图标 -->
              <template
                slot="custom"
                slot-scope="{ children, selected, fileInfo }"
              >
                <icon-font
                  :class="[selected && 'checked']"
                  :type="
                    (children && children.length > 0) || !fileInfo
                      ? 'icon-wenjianjia-'
                      : 'icon-jidiantuzhi'
                  "
                />
              </template>
              <template
                slot="title"
                slot-scope="{ nodeName, selected, fileInfo }"
              >
                <span :title="nodeName" :class="[selected && 'checked']">
                  {{ nodeName }}
                </span>
                <div class="operate-icon">
                  <!-- 关联 -->
                  <icon-font
                    type="icon-guanlian"
                    @click.stop="handleAgain(fileInfo)"
                    v-if="fileInfo && !fileInfo.dataSetId"
                  />
                  <!-- 操作 -->
                  <a-popover
                    placement="bottomLeft"
                    v-if="fileInfo && fileInfo.dataSetId"
                    @click.stop
                  >
                    <icon-font type="icon-icmore" />
                    <div slot="content" class="box-wrap">
                      <div @click="handleAgain(fileInfo)">
                        <icon-font type="icon-zhongxinguanlian" />重新关联
                      </div>
                      <div @click="handleCancelRelevance(fileInfo)">
                        <icon-font type="icon-guanlian" />取消关联
                      </div>
                    </div>
                  </a-popover>
                </div>
              </template>
            </a-tree>
          </a-spin>
        </div>
      </div>
    </div>
    <associationModel
      :visible.sync="associationModel.visible"
      :fileInfo="associationModel.fileInfo"
    ></associationModel>
  </div>
</template>

<script>
//图模联动
import { addAttributeByKey, flatTreeData } from "@/utils/util.js";
import { getModalTreeElemIdsById } from "@/api/bim";
import { Icon } from "ant-design-vue";
import iconfrontjs from "@/assets/IconFont/iconfont.js";
import cloneDeep from "lodash.clonedeep";
const iconFrontUrl = iconfrontjs;
const IconFont = Icon.createFromIconfontCN({
  scriptUrl: iconFrontUrl,
});
//关联模型
import associationModel from "./associationModel";
import { axios } from "@/utils/request";
export default {
  name: "artworkDrawer",
  inject: ["currentProject", "sceneSource"],
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },
  components: {
    IconFont,
    associationModel,
  },
  data() {
    return {
      keyWord: "",
      expandedKeys: [],
      autoExpandParent: true,
      selectedKeys: [],
      treeData: [],
      cloneTreeData: [],
      spinning: false,
      associationModel: {
        visible: false,
        fileInfo: {},
      },
      viewData: [],
      isHide: false,
    };
  },
  watch: {
    visible: {
      handler(val) {
        if (val) {
          this.isHide = true;
          this.getData();
        } else {
          this.isHide = false;
          this.handleClose();
        }
      },
      immediate: true,
    },
  },
  methods: {
    //打开关联弹窗
    handleAgain(fileInfo = {}) {
      this.associationModel.fileInfo = fileInfo;
      this.associationModel.visible = true;
    },

    //请求属性数据
    getData() {
      this.spinning = true;
      return new Promise((resolve, reject) => {
        let { orgCode } = this.currentProject();
        if (!orgCode) {
          return;
        }
        axios
          .post(
            `/probusiness/bimCadClassify/getTreeFileByProCode?proCode=${orgCode}`,
            {},
            {
              headers: {
                "Content-Type": "application/json",
              },
            }
          )
          .then((res) => {
            let { data } = res;
            let filterData = addAttributeByKey(
              null,
              "scopedSlots",
              { icon: "custom" },
              data,
              "children"
            );
            let flatData = flatTreeData(data, "children");
            this.expandedKeys = flatData.map((v) => v.id).filter((v) => v);
            this.treeData = filterData;
            this.cloneTreeData = cloneDeep(filterData ?? []);
            resolve();
          })
          .catch((_) => {
            this.expandedKeys = [];
            this.treeData = [];
            this.cloneTreeData = [];
            reject();
          })
          .finally((_) => {
            this.spinning = false;
          });
      });
    },

    //树展开
    onExpand(expandedKeys) {
      this.expandedKeys = expandedKeys;
      this.autoExpandParent = false;
    },

    //树选择
    onSelect(selectedKeys, info) {
      let { fileInfo, id } = info.node.dataRef;
      if (this.selectedKeys.includes(id)) {
        return;
      }
      if (fileInfo) {
        this.selectedKeys = [id];
        this.loadCADbIM(fileInfo);
      } else {
        this.$message.warning("暂无CAD图纸文件！");
      }
    },

    //取消关联
    handleCancelRelevance(fileInfo = {}) {
      let { uuid } = fileInfo;
      let that = this;
      that.$confirm({
        title: "提示",
        content: "确定取消关联吗？取消之后不可恢复！",
        okText: "确定",
        cancelText: "取消",
        icon: () =>
          that.$createElement("a-icon", {
            props: {
              key: "warning",
              type: "exclamation-circle",
              twoToneColor: "#faad14",
            },
          }),
        onOk() {
          return new Promise((resolve, reject) => {
            axios
              .post(
                `/probusiness/bimCadFile/updateData`,
                {
                  uuid,
                  dataSetId: "",
                  componentId: "",
                },
                {
                  headers: {
                    "Content-Type": "application/json",
                  },
                }
              )
              .then((res) => {
                let { statusCode, message } = res;
                if (statusCode == 200 && message == "success") {
                  that.$message.success("操作成功");
                  that.getData();
                  if (that.selectedKeys.includes(uuid)) {
                    that.loadCADbIM({
                      ...fileInfo,
                      dataSetId: "",
                      componentId: "",
                    });
                  }
                  resolve();
                } else {
                  that.$message.error(message ?? "操作失败，请稍后重试！");
                }
              })
              .catch((_) => {
                that.$message.error("操作失败，请稍后重试！");
              })
              .finally((_) => {
                that.submitLoading = false;
              });
          }).catch(() => console.log("Oops errors!"));
        },
      });
    },

    //加载cad和bim
    loadCADbIM(fileInfo, type) {
      this.$parent.loading = true;
      let { dataSetId, uuid, componentId, unit } = fileInfo;
      let proms = [];
      if (type == "cancel") {
        proms = [this.getCADModelData(uuid)];
      } else {
        proms = [this.getCADModelData(uuid), this.getSetModelData(dataSetId)];
      }
      Promise.all(proms).then((result) => {
        let [dwg, bim] = result;
        this.unloadAllDataSet();
        document.addEventListener("RECADLoadFinish", (e) => {
          this.RECADLoadFinish(e, bim);
          this.$parent.loading = false;
        });
        document.addEventListener("REDataSetLoadFinish", (e) => {
          if (this.visible) {
            BlackHole3D.Camera.resetCamLocate();
            BlackHole3D.Camera.resetCamBound();
          } else {
            // this.$parent.setDefaultViewport();
          }

          bim &&
            bim.forEach((v) => {
              let { dataSetId } = v;
              if (componentId) {
                this.getElemIds(dataSetId, componentId);
              } else {
                BlackHole3D.BIM.setElemAlpha(dataSetId, [], 255);
              }
            });
        });
        setTimeout((_) => {
          //加载cad
          if (dwg?.[0]?.resourcesAddress) {
            BlackHole3D.setViewMode(
              BlackHole3D.REVpTypeEm.None,
              BlackHole3D.REVpTypeEm.CAD,
              BlackHole3D.REVpRankEm.Single
            );
            BlackHole3D.CAD.loadCAD(
              dwg?.[0]?.resourcesAddress,
              BlackHole3D.RECadUnitEm[unit ?? "CAD_UNIT_Meter"],
              1.0
            );
          }
          //加载模型
          if (bim && bim.length > 0) {
            let dataSetList = [];
            bim.forEach((v) => {
              let { resourcesAddress, dataSetId } = v;
              dataSetList.push({
                dataSetId,
                resourcesAddress,
                useTransInfo: true,
                transInfo: [
                  [1, 1, 1],
                  [0, 0, 0, 1],
                  [0, 0, 0.0],
                ],
              });
            });
            BlackHole3D.Model.loadDataSet(dataSetList);
          }
        }, 300);
      });
      return;
    },

    //查询节点对应的构件id集合
    getElemIds(dataSetId, nodeId) {
      let dataSets = [
        {
          childNodeId: nodeId,
          dataSetId,
        },
      ];
      return new Promise((resolve, reject) => {
        getModalTreeElemIdsById({ dataSets })
          .then((res) => {
            let { data } = res;
            let ids = data?.[0]?.childNodeIds ?? [];
            if (this.visible) {
              BlackHole3D.BIM.setElemAlpha(dataSetId, [], 0);
            }
            setTimeout((_) => {
              BlackHole3D.BIM.setElemAlpha(dataSetId, ids, 255);
            }, 50);
            resolve();
          })
          .catch((_) => {
            resolve([]);
          })
          .finally((_) => {});
      });
    },

    RECADLoadFinish(isSuccess, bimData = []) {
      if (isSuccess) {
        BlackHole3D.canvas.focus(); //为了解决键盘事件的冲突
        console.log("CAD加载成功!");
        //设置横向双屏显示，左边为CAD，右边为BIM场景
        if (bimData.length > 0) {
          BlackHole3D.setViewMode(
            BlackHole3D.REVpTypeEm.CAD,
            BlackHole3D.REVpTypeEm.BIM,
            BlackHole3D.REVpRankEm.LR
          );
        } else {
          BlackHole3D.setViewMode(
            BlackHole3D.REVpTypeEm.CAD,
            BlackHole3D.REVpTypeEm.None,
            BlackHole3D.REVpRankEm.Single
          );
        }
      }
    },

    //卸载已有模型
    unloadAllDataSet() {
      BlackHole3D.Model.unloadAllDataSet();
    },

    //卸载所有CAD
    unloadCAD() {
      BlackHole3D.setViewMode(
        "",
        BlackHole3D.REVpTypeEm.BIM,
        BlackHole3D.REVpRankEm.LR
      );
    },

    //加载原有模型
    loadOriginalDataSet() {
      let dataSetList = [];
      (this.$parent.dataSetListSource ?? []).forEach((v) => {
        let { dataSetId, resourcesAddress, dataSetCrs, offsetData } = v;
        let { rotate, scale, translation } = offsetData ?? {
          rotate: "0 0 0 1",
          scale: "1 1 1",
          translation: "0 0 0",
        };
        dataSetList.push({
          dataSetId,
          resourcesAddress,
          useTransInfo: true,
          transInfo: [
            scale.split(" ").map((v) => Number(v)),
            rotate.split(" ").map((v) => Number(v)),
            translation.split(" ").map((v) => Number(v)),
          ],
          dataSetCRS: dataSetCrs,
        });
      });
      BlackHole3D.Model.loadDataSet(dataSetList);
    },

    //查询CAD地址
    getCADModelData(uuid = "") {
      this.loading = true;
      return new Promise((resolve, reject) => {
        axios
          .post(
            `/probusiness/bimCadFile/project/cadFile/list?uuid=${uuid}`,
            {},
            {
              headers: {
                "Content-Type": "application/json",
              },
            }
          )
          .then((res) => {
            resolve(res?.data ?? []);
          })
          .catch((_) => {
            reject([]);
          })
          .finally((_) => {});
      });
    },

    //查询BIM地址
    getSetModelData(dataSetId = "") {
      if (!dataSetId) {
        return;
      }
      return new Promise((resolve, reject) => {
        axios
          .post(
            `/probusiness/blackHole3D/project/dataSet/viewDataSetModel`,
            {
              dataSetIds: [dataSetId],
            },
            {
              headers: {
                "Content-Type": "application/json",
              },
            }
          )
          .then((res) => {
            resolve(res?.data?.modelData ?? []);
          })
          .catch((_) => {
            this.viewData = [];
            resolve([]);
          });
      });
    },

    //搜索
    filterTreeData() {
      let { keyWord, cloneTreeData } = this;
      let cloneData = cloneDeep(cloneTreeData);
      this.treeData = this.filterTree(cloneData, "children", (node) =>
        node.nodeName.includes(keyWord)
      );
    },

    //过滤树形数据
    filterTree(data, children = "children", filterFunc) {
      return data
        .filter((node) => {
          // 如果当前节点符合条件，直接返回true
          if (filterFunc(node)) {
            return true;
          }
          // 如果当前节点有子节点，递归过滤子节点
          if (node[children]) {
            node[children] = this.filterTree(
              node[children],
              children,
              filterFunc
            );
            // 如果过滤后的子节点不为空，说明当前节点需要保留
            return node[children].length > 0;
          }
          // 当前节点不符合条件，也没有子节点或子节点不符合条件，返回false
          return false;
        })
        .map((node) => {
          // 创建新对象，避免修改原始数据
          return {
            ...node,
            [children]: node[children]
              ? this.filterTree(node[children], children, filterFunc)
              : [],
          };
        });
    },

    handleClose() {
      if (this.selectedKeys.length > 0) {
        this.unloadAllDataSet();
        this.unloadCAD();
        setTimeout((_) => {
          this.loadOriginalDataSet();
        }, 300);
      }
      this.expandedKeys = [];
      this.selectedKeys = [];
      this.treeData = [];
      this.cloneTreeData = [];
      this.$emit("update:visible", false);
      this.$emit("close", false);
    },

    hanleVisible(flag) {
      this.isHide = flag;
    },
  },
};
</script>

<style lang="less" scoped>
.artworkDrawer-container {
  position: absolute;
  width: 300px;
  height: 100%;
  top: 0;
  pointer-events: none;
  transition: 0.3s;
  left: 10px;
  box-sizing: border-box;
  padding: 16px 0 20px 0;
  z-index: 99;
  &.hide {
    left: -100%;
  }
  .artworkDrawer-body {
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: 6px;
    pointer-events: all;
    .header {
      flex-shrink: 0;
      height: 36px;
      background: #f0f0f0;
      border-radius: 6px 6px 0px 0px;
      border: 1px solid #d9d9d9;
      display: flex;
      align-items: center;
      box-sizing: border-box;
      padding: 0 16px;
      font-size: 16px;
      color: #333333;
      position: relative;
      .anticon-close {
        color: #8c8c8c;
        font-size: 15px;
        cursor: pointer;
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        right: 10px;
      }
    }
    .body {
      flex: 1;
      background: #fff;
      padding: 0 0 10px 0;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      .search-condition {
        flex-shrink: 0;
        padding: 16px 16px 4px 16px;
        position: relative;
        input {
          padding-right: 36px;
        }
        .anticon {
          color: #8c8c8c;
          position: absolute;
          right: 28px;
          font-size: 20px;
          cursor: pointer;
          top: 20px;
        }
      }
      .tree-container {
        flex: 1;
        padding: 0 10px;
        overflow: auto;
        overflow-x: hidden;
        position: relative;
        /deep/.ant-tree {
          li {
            width: 100%;
            .ant-tree-node-content-wrapper {
              position: relative;
              width: calc(100% - 34px);
              padding: 0 5px 0 0;
              .ant-tree-iconEle {
                color: #f3ab1f;
                font-size: 16px;
                .checked {
                  color: #1677ff;
                }
              }
              .ant-tree-title {
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                display: inline-block;
                max-width: calc(100% - 40px);
                .checked {
                  color: #1677ff;
                }
                .operate-icon {
                  position: absolute;
                  top: 55%;
                  right: 0;
                  transform: translateY(-50%);
                  .anticon {
                    font-size: 18px;
                  }
                }
              }
            }
          }
        }
        /deep/.ant-empty {
          position: absolute;
          left: 50%;
          top: 50%;
          transform: translate(-50%, -50%);
        }
      }
    }
  }
}
.box-wrap {
  font-family: Microsoft YaHei, Microsoft YaHei;
  font-weight: 400;
  font-size: 14px;
  color: #333333;
  line-height: 32px;
  div {
    cursor: pointer;
    user-select: none;
  }
  .anticon {
    margin-right: 10px;
    font-size: 14px;
  }
}
</style>
